package service

import (
	"seat-service/initialization"
	"seat-service/model"
	"seat-service/model/dto"
	"strings"
)

type MenuService struct {
}

// TODO 多表查询 查询menus表及casbin_rule表下当前用户可访问的菜单
func (*MenuService) GetButtonMenusByRoleAndType(role string) (menu []model.Menu, err error) {
	err = initialization.DB.Table("menus").
		Select("menus.*").
		Joins("JOIN casbin_rule ON menus.id = casbin_rule.v1 AND menus.roles LIKE CONCAT('%',casbin_rule.v0,'%')").
		Where("menus.type = 4 AND ? LIKE CONCAT('%',casbin_rule.v0,'%')", role).
		Find(&menu).Error
	return
}

// GetMenus 获取菜单
func (*MenuService) GetMenus(Id uint) (menu model.Menu, err error) {
	err = initialization.DB.Model(&model.Menu{}).Where("id = ?", Id).Find(&menu).Error
	return
}

// GetMenusByGrade 获取指定层级菜单菜单
func (*MenuService) GetMenusByGrade(parentId uint) (menus []model.Menu, err error) {
	err = initialization.DB.Table("menus").Where("parent_id = ?", parentId).Preload("Children").Preload("Children").Find(&menus).Error
	return
}

func (m *MenuService) PreloadChildren(menu *model.Menu) {
	initialization.DB.Preload("Children").Order("sort").Find(&menu.Children, "parent_id = ?", menu.ID)
	for i := range menu.Children {
		m.PreloadChildren(&menu.Children[i])
	}
}

// GetFirstMenus 获取一级菜单
func (*MenuService) GetFirstMenus() (menus []*model.Menu, err error) {
	// TODO 问题 查询parent_id = 0 为啥只查询type=2的
	err = initialization.DB.Table("menus").Where("parent_id = 0").Order("sort").Find(&menus).Error
	return
}

// GetRouter 获取路由菜单
func (*MenuService) GetRouter() (menus []*model.Menu, err error) {
	// TODO preload 预加载 使用外键
	err = initialization.DB.Table("menus").Where("parent_id = 0").Preload("Children").Find(&menus).Error
	return
}

// UpdatesMenu 修改菜单
func (*MenuService) UpdatesMenu(par *model.Menu) (err error) {
	err = initialization.DB.Where("id = ?", par.ID).Updates(par).Error
	return
}

// SaveMenu 保存菜单
func (*MenuService) SaveMenu(par *model.Menu) (err error) {
	err = initialization.DB.Save(par).Error
	return
}

// DeleteMenu 删除菜单
func (*MenuService) DeleteMenu(id int) (err error) {
	err = initialization.DB.Where("id = ? OR parent_id = ?", id, id).Delete(&model.Menu{}).Error
	return err
}

func (*MenuService) ChangeControlRole(ruleInformation dto.RuleID) (err error) {
	tx := initialization.DB.Begin()
	//希望增加权限的菜单
	for _, saveId := range ruleInformation.SaveIds {
		var menu model.Menu
		//查询该角色对此菜单是否有权限
		err = tx.Where("roles LIKE BINARY ? and id = ?", "%"+ruleInformation.Role+"%", saveId).Find(&menu).Error
		if err != nil {
			tx.Rollback()
			return
		}
		if menu.ID == 0 {
			//如果当前角色对此菜单没有权限,在roles字段拼接 , 然后更新数据
			err = tx.Where("id = ?", saveId).Find(&menu).Error
			if err != nil {
				tx.Rollback()
				return
			}
			menu.Roles = menu.Roles + " " + ruleInformation.Role
			//执行更新操作
			err = tx.Where("id = ?", saveId).Updates(&menu).Error
			if err != nil {
				tx.Rollback()
				return
			}
		}
	}
	//希望删除该角色对某些菜单的权限
	for _, deleteId := range ruleInformation.DeleteIds {
		var menu model.Menu
		//查询出这些菜单的roles字段 , 更新字符串
		err = tx.Where("id = ?", deleteId).Find(&menu).Error
		if err != nil {
			tx.Rollback()
			return
		}
		//更新字符串
		menu.Roles = strings.Replace(menu.Roles, ruleInformation.Role, "", -1)
		//更新数据库中的数据
		err = tx.Where("id = ?", deleteId).Updates(&menu).Error
		if err != nil {
			tx.Rollback()
			return
		}
	}
	tx.Commit()
	return err
}
